#include <string.h>
#include <iostream>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "database.h"

void help()
{
    std::cout << "You did it wrong!" << std::endl;
}

bool file_exists(char const *path)
{
    struct stat stfile;
    int stat_status = stat(path, &stfile);
    return stat_status == 0;
}

int initialize(bool forced = false)
{
    int status = 0;
    // check if home directory contains .boerse directory
    // create it if it does not exist
    status = mkdir("~/.boerse", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    if(status != 0)
    {
        switch(errno)
        {
            case EACCES:
                std::cerr << "Search permission is denied on a component of the path prefix, or write permission is denied on the parent directory of the directory to be created." << std::endl;
                return 1;
            case EEXIST: // that's ok
                break;
            case ELOOP:
                std::cerr << "A loop exists in symbolic links encountered during resolution of the path argument." << std::endl;
                return 1;
            case EMLINK:
                std::cerr << "The link count of the parent directory would exceed {LINK_MAX}." << std::endl;
                return 1;
            case ENAMETOOLONG:
                std::cerr << "The length of the path argument exceeds {PATH_MAX} or a pathname component is longer than {NAME_MAX}." << std::endl;
                return 1;
            case ENOENT:
                std::cerr << "A component of the path prefix specified by path does not name an existing directory or path is an empty string." << std::endl;
                return 1;
            case ENOSPC:
                std::cerr << "The file system does not contain enough space to hold the contents of the new directory or to extend the parent directory of the new directory." << std::endl;
                return 1;
            case ENOTDIR:
                std::cerr << "A component of the path prefix is not a directory." << std::endl;
                return 1;
            case EROFS:
                std::cerr << "The parent directory resides on a read-only file system." << std::endl;
                return 1;
        }
    }
    
    // check if database file exists
    bool db_exists = file_exists("~/.boerse/db.sql");
    if(db_exists && !forced)
    {
        std::cerr << "I will not wipe the existing database file until you force it." << std::endl;
        help();
        return 1;
    } else if(db_exists)
    {
        status = remove("~/.boerse/db.sql");
        if(status != 0)
        {
            switch(errno)
            {
                case EACCES:
                    std::cerr << "Search permission is denied for a component of the path prefix, or write permission is denied on the directory containing the directory entry to be removed." << std::endl;
                    return 1;
                case EBUSY:
                    std::cerr << "The file named by the path argument cannot be unlinked because it is being used by the system or another process and the implementation considers this an error." << std::endl;
                    return 1;
                case ELOOP:
                    std::cerr << "A loop exists in symbolic links encountered during resolution of the path argument." << std::endl;
                    return 1;
                case ENAMETOOLONG:
                    std::cerr << "The length of the path argument exceeds {PATH_MAX} or a pathname component is longer than {NAME_MAX}." << std::endl;
                    return 1;
                case ENOENT:
                    std::cerr << "A component of path does not name an existing file or path is an empty string." << std::endl;
                    return 1;
                case ENOTDIR:
                    std::cerr << "A component of the path prefix is not a directory." << std::endl;
                    return 1;
                case EPERM:
                    std::cerr << "The file named by path is a directory, and either the calling process does not have appropriate privileges, or the implementation prohibits using unlink() on directories." << std::endl;
                    return 1;
                case EROFS:
                    std::cerr << "The directory entry to be unlinked is part of a  read-only  file system." << std::endl;
                    return 1;
                case ETXTBSY:
                    std::cerr << "The entry to be unlinked is the last directory entry to a pure procedure (shared text) file that is being executed." << std::endl;
                    return 1;
            }
        }
    }
    
    // create the initial database file
    Database db("~/.boerse/db.sql");
    if(db.open())
    {
        std::cerr << "Error while open database." << std::endl;
        return 1;
    }
    if(db.initialize())
    {
        std::cerr << "Error while database initialization." << std::endl;
        return 1;
    }
    return 0;
}

int main(int argc, char** argv)
{
    bool init_flag = false;
    bool forced_flag = false;
    
    if(argc <= 1)
    {
        help();
        return 1;
    }
    
    for(int i = 1; i < argc; ++i)
    {
        if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0)
        {
            help();
            return 0;
        }
        else if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--force") == 0)
        {
            forced_flag = true;
        }
        else if(strcmp(argv[i], "init") == 0)
        {
            init_flag = true;
        }
    }
    
    if(init_flag)
    {
        return initialize(forced_flag);
    }
    return 0;
}